#include "Socket.hpp"
#include <vector>

using namespace socket_ns;

const static int N = sizeof(fd_set) * 8;
const static int defaultfd = -1;

class SelectServer
{

public:
    SelectServer(uint16_t port)
        : _port(port), _listensock(make_unique<TcpSocket>()), assist(N, defaultfd)
    {
        Analyze addr("0", _port);
        _listensock->BuildTcpServerSocket(addr);

        assist[0] = _listensock->getfd();
    }

    ~SelectServer() {}

    void Loop()
    {
        while (true)
        {
            fd_set rfds;
            FD_ZERO(&rfds);

            // 将所有合法的fd设置进rfds中
            int maxfd = assist[0];
            for (int i = 0; i < N; i++)
            {
                if (assist[i] == defaultfd)
                    continue;
                FD_SET(assist[i], &rfds);

                if (maxfd < assist[i])
                    maxfd = assist[i];
            }

            timeval timeout = {1, 0};
            int n = select(maxfd + 1, &rfds, nullptr, nullptr, nullptr);
            switch (n)
            {
            case 0:
                Log(Debug, "timeout...");
                break;
            case -1:
                Log(Error, "select error");
                break;
            default:
                Log(Info, "select fd num: %d", n);
                HandlerEvent(rfds);
                break;
            }
        }
    }

    void HandlerEvent(fd_set &rfds)
    {
        for (int i = 0; i < N; i++)
        {
            // 这里判断守监管的fd是否就绪，监管的fd在assist中
            if (assist[i] == defaultfd)
                continue;
            if (FD_ISSET(assist[i], &rfds))
            {
                if (assist[i] == _listensock->getfd())
                {
                    AcceptClientRequest(); // listen套接字获取普通套接字加入辅助数组
                }
                else
                {
                    HandlerNormalRequest(i); // 处理普通套接字的请求
                }
            }
        }
    }

    // 参数：已就绪的普通fd的位置
    void HandlerNormalRequest(int pos)
    {
        char buffer[N];
        int n = recv(assist[pos], buffer, sizeof(buffer) - 1, 0);

        if (n > 0)
        {
            cout << buffer << endl;

            string rest = "response: ";
            rest += buffer;
            send(assist[pos], rest.c_str(), rest.size(), 0);
        }
        else
        {
            close(assist[pos]);
            assist[pos] = defaultfd;
        }
    }

    void AcceptClientRequest()
    {
        Analyze an("0", _port);
        sock_addr addr = _listensock->Accept(an); // 通过返回值，我们可以拿到普通socketfd

        int socketfd = addr->getfd();
        if (socketfd < 0)
            return;

        int pos = 1;
        for (; pos < N; pos++)
        {
            if (assist[pos] == defaultfd)
                break;
        }

        if (pos == N)
        {
            close(socketfd);
            Log(Warning, "FULL");
            return;
        }
        else if (pos < N)
        {
            assist[pos] = socketfd;
            Log(Info, "AcceptClientRequest Set Success");
        }
    }

private:
    uint16_t _port;
    unique_ptr<Socket> _listensock;

    vector<int> assist;
};